import java.awt.*;
import java.awt.event.*;
import java.nio.IntBuffer;
import java.util.List;

import javax.media.opengl.*;
import javax.media.opengl.awt.*;
import javax.media.opengl.glu.*;
import javax.swing.*;
import com.jogamp.common.nio.*;
import com.jogamp.opengl.util.*;

public class Project implements GLEventListener {
	private static JFrame appFrame;
	private static SceneGraphNode sceneGraphRoot;
	private static boolean pickNextFrame;
	private static Point pickedPoint;
	private static double left, right, top, bottom;
	private static int displayListID = -1;
	private static Point init;
	private static Point end;
	private float newScale; 
	private static List<SceneGraphNode> pickedNode;
	
	public static void main(String[] args) {
		GLProfile.initSingleton();
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				(new Project()).createAndShowGUI();
			}
		});
	}

	private void createAndShowGUI() {
		// Fix for background flickering
		// System.setProperty("sun.awt.noerasebackground", "true");
		
		GLProfile profile = GLProfile.getDefault();
		GLCapabilities capabilities = new GLCapabilities(profile);
		GLCanvas canvas = new GLCanvas(capabilities);
		canvas.addGLEventListener(this);
		canvas.addMouseListener(new MouseAdapter() {
			
		  
		  /*public void mouseClicked(MouseEvent e) {
				pickNextFrame = true;
				pickedPoint = new Point(e.getX(), e.getY());
			 System.out.println(e.getX() + ", " + e.getY());
			 
			
			}*/
			
			//when mouse is pressed, pick the object, and get coords
			
			public void mousePressed(MouseEvent e) {
        pickNextFrame = true;
        pickedPoint = new Point(e.getX(), e.getY());
        init = pickedPoint;
        
        
        //System.out.println(e.getX() + ", " + e.getY());
        System.out.println(init.x + ",, " + init.y);
			}
			
			
			public void mouseReleased(MouseEvent e) {
			  pickNextFrame = false;
			  end = new Point(e.getX(), e.getY());
        //end = pickedPoint;
        //System.out.println(e.getX() + ", " + e.getY());
        System.out.println(end.x + ",, " + end.y);
			  
			}
			
		});

		SceneGraphNode rectangle = new Rectangle();
		rectangle.scale = 0.5f;
		rectangle.translateX = 0f;
		rectangle.translateY = 0f;
		rectangle.rotation = 0f;
		
		SceneGraphNode triforce = new Triforce();
		triforce.scale = .5f;
		triforce.translateX = 1f;
		triforce.translateY = -1f;
		triforce.rotation = 0f;
		
		SceneGraphNode triangle = new Triangle();
		triangle.scale = 1f;
		triangle.translateX = -1f;
		triangle.translateY = -1f;
		triangle.rotation = 0f;
		
		SceneGraphNode circle = new Circle();
    circle.scale = 0.5f;
    circle.translateX = 1f;
    circle.translateY = 1f;
    circle.rotation = 0f;
    
		SceneGraphNode set = new SceneGraphNode();
		set.addChild(rectangle);
		set.addChild(triangle);
		set.addChild(triforce);
		set.addChild(circle);
		
		sceneGraphRoot = set;
		
		
		appFrame = new JFrame("Project");
		appFrame.setJMenuBar(createMenuBar());
		appFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		appFrame.setMinimumSize(new Dimension(256, 256));
		appFrame.add(canvas);
		appFrame.pack();
		if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH))
			appFrame.setExtendedState(appFrame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
		appFrame.setVisible(true);
	}
	private JMenuBar createMenuBar() {
		final JMenuBar bar = new JMenuBar();
		bar.add(createMenuItems());
		return bar;
	}
	
	private JMenu createMenuItems() {
		final JMenu menu = new JMenu("Shapes...");
		menu.add(createCircle());
		menu.add(createTriangle());
		menu.add(createRectangle());
		menu.add(createTriforce());
		menu.add(removeObject());
		return menu;
	}
	
	private JMenuItem removeObject() {
		final JMenuItem removeObject = new JMenuItem("Remove clicked shape");
		removeObject.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (!pickedNode.isEmpty())
				sceneGraphRoot.removeChild(pickedNode.get(0));
			}
		});
		return removeObject;
	}
	
	private JMenuItem createCircle() {
		final JMenuItem circle = new JMenuItem("Add Circle");
		circle.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SceneGraphNode c = new Circle();
				c.scale = .5f;
				sceneGraphRoot.addChild(c);
			}
		});
		return circle;
	}
	
	private JMenuItem createRectangle() {
		final JMenuItem item = new JMenuItem("Add Rectangle");
		item.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SceneGraphNode n = new Rectangle();
				n.scale = .5f;
				sceneGraphRoot.addChild(n);
			}
		});
		return item;
	}
	
	private JMenuItem createTriangle() {
		final JMenuItem item = new JMenuItem("Add Triangle");
		item.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SceneGraphNode n = new Triangle();
				sceneGraphRoot.addChild(n);
			}
		});
		return item;
	}
	
	private JMenuItem createTriforce() {
		final JMenuItem item = new JMenuItem("Add Triforce");
		item.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				SceneGraphNode n = new Triforce();
				n.scale = .5f;
				sceneGraphRoot.addChild(n);
			}
		});
		return item;
	}

	public void display(GLAutoDrawable drawable) {

	    
	  GL2 gl = drawable.getGL().getGL2();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);

		
		if (pickNextFrame) {
			GLU glu = GLU.createGLU(gl);
			int viewport[] = new int[4];
			gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
			gl.glMatrixMode(GL2.GL_PROJECTION);
			gl.glPushMatrix();
			gl.glLoadIdentity();
			glu.gluPickMatrix(pickedPoint.x, (double)(viewport[3] - pickedPoint.y), 1, 1, viewport, 0);
			
			gl.glOrtho(left, right, bottom, top, -1, 1);
			gl.glMatrixMode(GL2.GL_MODELVIEW);
			
			transformers( drawable, sceneGraphRoot.getPicked(drawable));
			
			pickedNode = sceneGraphRoot.getPicked(drawable);
			
			System.out.println(sceneGraphRoot.getPicked(drawable));
			
			gl.glMatrixMode(GL2.GL_PROJECTION);
			gl.glPopMatrix();
			gl.glMatrixMode(GL2.GL_MODELVIEW);
			pickNextFrame = false;
		}
		  
		/*
		if (displayListID == -1) {
			displayListID = 1;
			gl.glNewList(displayListID, GL2.GL_COMPILE_AND_EXECUTE);
			sceneGraphRoot.render(drawable);
			gl.glEndList();
		} else
			gl.glCallList(displayListID);*/
		  
		  sceneGraphRoot.render(drawable);
		  
		  //sceneGraphRoot.rotation++;

	}

	public void dispose(GLAutoDrawable drawable) {
	}

	public void init(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();
		gl.glClearColor(0, 0, 0, 0);
		IntBuffer selectBuffer = Buffers.newDirectIntBuffer(3);
		gl.glSelectBuffer(selectBuffer.capacity(), selectBuffer);
		FPSAnimator fps = new FPSAnimator(drawable, 30);
		fps.start();
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		final double UNIT = 4;
		
		if (width < height) {
			left = -UNIT / 2;
			right = UNIT / 2;
			top = (double)height / width * UNIT / 2;
			bottom = -top;
		} else {
			top = UNIT / 2;
			bottom = -UNIT / 2;
			right = (double)width / height * UNIT / 2;
			left = -right;
		}
		
		GL2 gl = drawable.getGL().getGL2();
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glOrtho(left, right, bottom, top, -1, 1);
		gl.glMatrixMode(GL2.GL_MODELVIEW);
	}

	  public void transformers(GLAutoDrawable drawable, List<SceneGraphNode> list) {
	    
	    
	    for (SceneGraphNode scn : list) {
	      
	      /*
	            testing translateX/Y and coordinate system
	      
	      scn.translateX = 0;
	      scn.translateY = 1;

	            scaleFromGUI is a variable passed by input from the button, just a var 
	      
	      scn.scaleFromGUI = 1.6f;
	      scn.scale = scn.scaleFromGUI;
	    */
	    
	    }
	    
	    
	    
	    
	  }








}

/*
 * translate x,y pixels to x,y coords, translate() 
 * clicked object from init to end
 * scale if needed
 * build/remove if needed
 * re-render graph
 */



